<template>
  <div id="module"></div>
</template>

<script>
import * as THREE from "three";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { onMounted } from "vue";

export default {
  setup() {
    const data = {
      moduleUrl: "modules/people/rick/scene.gltf",
      moduleHomeUrl: "modules/people/house/scene.gltf",
      mortyUrl: "modules/people/morty/scene.gltf",
      scene: null,
      renderer: null,
      camera: null,
      orbitControls: null,
      model: null,
      homeModel: null,
      light: null
    };

    onMounted(() => {
      methods.init();
      methods.loadModel();
      methods.animate();
      methods.getFloor();
      methods.addDirectionalLight();
      methods.addPointer();
    });

    const methods = {
      init: () => {
        let container = document.getElementById("container");
        // 摄像机
        data.camera = new THREE.PerspectiveCamera(
          30,
          window.innerWidth / window.innerHeight,
          0.1,
          1000
        );
        // 特别注意，相机的位置要大于几何体的尺寸
        data.camera.position.z = 620;
        data.camera.position.x = 80;
        data.camera.position.y = 50;
        data.scene = new THREE.Scene();
        data.renderer = new THREE.WebGLRenderer({
          // 抗锯齿性
          antialias: true
        });
        // 设置背景色
        data.renderer.setClearColor("#CDE3F1", 1.0);
        data.renderer.setSize(window.innerWidth, window.innerHeight);
        container.appendChild(data.renderer.domElement);
        data.renderer.shadowMap.enabled = true;
        data.renderer.outputEncoding = THREE.sRGBEncoding;

        // 环境光不能用来投射阴影，因为它没有方向。
        var ambienLight = new THREE.AmbientLight("#ffffff", 0.9);
        data.scene.add(ambienLight);

        // 初始化轨道控制器
        // 还需要配合animate，不断循环渲染，达到用鼠标旋转物体的作用。
        data.orbitControls = new OrbitControls(
          data.camera,
          data.renderer.domElement
        );
        // 创建坐标轴对象
        var axes = new THREE.AxesHelper(500);
        //将坐标轴添加进场景
        data.scene.add(axes);
        // 窗口大小自适应
        window.addEventListener("resize", methods.onWindowResize, false);
      },

      animate: () => {
        requestAnimationFrame(methods.animate);
        data.renderer.render(data.scene, data.camera);
      },

      onWindowResize: () => {
        data.camera.aspect = window.innerWidth / window.innerHeight;
        data.camera.updateProjectionMatrix();
        data.renderer.setSize(window.innerWidth, window.innerHeight);
      },

      // 加载模型
      loadModel: () => {
        //加载rick
        var loader = new GLTFLoader();
        // 路径要特别注意，默认是从public读取的，模型文件必须放在public下，并且路径前的public要省略
        // 加载rick
        loader.load(
          data.moduleUrl,
          gltf => {
            // 设置模型尺寸
            data.model = gltf.scene;
            data.model.scale.set(3, 3, 3);
            data.model.position.y = 0;
            data.model.position.z = 85;
            data.model.position.x = 85;
            // 模型是否否需要阴影
            gltf.scene.traverse(obj => {
              obj.castShadow = true;
              obj.receiveShadow = true;
            });

            data.scene.add(data.model);
          },
          undefined,
          error => {
            console.error(error);
          }
        );

        // morty
        loader.load(
          data.mortyUrl,
          gltf => {
            // 设置模型尺寸
            data.model = gltf.scene;
            data.model.scale.set(8, 8, 8);
            data.model.position.y = 0;
            data.model.position.z = 85;
            data.model.position.x = 45;
            // 模型是否否需要阴影
            gltf.scene.traverse(obj => {
              obj.castShadow = true;
              obj.receiveShadow = true;
            });

            data.scene.add(data.model);
          },
          undefined,
          error => {
            console.error(error);
          }
        );

        // 加载家
        loader.load(
          data.moduleHomeUrl,
          gltf => {
            // 尺寸
            data.homeModel = gltf.scene;
            data.homeModel.scale.set(5, 5, 5);
            data.homeModel.position.y = 0;
            data.homeModel.position.x = -50;
            // 阴影
            gltf.scene.traverse(obj => {
              obj.castShadow = true;
              obj.receiveShadow = true;
            });

            data.scene.add(data.homeModel);
          },
          undefined,
          error => {
            console.error(error);
          }
        );

        // 让gltf能产生投影
        loader.castShadow = true;
      },

      // 添加标注
      addPointer() {
        // 标记点组合
        var gLabel = new THREE.Group();
        var texture = new THREE.CanvasTexture(
          methods.getCanvasFont(200, 200, 200, "#000")
        );
        var fontMesh = new THREE.Sprite(
          new THREE.SpriteMaterial({
            map: texture
          })
        );
        fontMesh.scale.x = 500;
        fontMesh.scale.y = 500;
        fontMesh.position.set(200, 200, 35);
        gLabel.add(fontMesh);
      },

      // 标注 - 文字函数
      getCanvasFont(w, h, textValue, fontColor) {
        var canvas = document.createElement("canvas");
        canvas.width = w;
        canvas.height = h;
        var ctx = canvas.getContext("2d");
        ctx.fillStyle = "#ff0000"; //textBackground;
        ctx.fillRect(0, 0, w, h);
        ctx.font = h + "px '微软雅黑'";
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";
        ctx.fillStyle = fontColor;
        ctx.fillText(textValue, w / 2, h / 2 + 3);
        //document.body.appendChild(canvas);
        return canvas;
      },

      // 创建地板
      getFloor: () => {
        // 创建地平面并设置大小
        var textureLoader = new THREE.TextureLoader();
        var grass = require("../../assets/image/grass.jpg");
        var cubeMaterial = new THREE.MeshStandardMaterial({
          map: textureLoader.load(grass)
        });
        cubeMaterial.map.wrapS = THREE.RepeatWrapping;
        cubeMaterial.map.wrapT = THREE.RepeatWrapping;
        cubeMaterial.map.repeat.set(8, 8);
        var planeGeometry = new THREE.PlaneGeometry(1000, 1000);
        var plane = new THREE.Mesh(planeGeometry, cubeMaterial);

        // 设置平面位置并旋转
        plane.rotation.x = -0.5 * Math.PI;
        plane.position.y = -1;
        plane.position.z = 0;
        //是否接受阴影投射 (非常重要)
        plane.receiveShadow = true;
        data.scene.add(plane);
      },

      //添加DirectionalLight，用来模拟太阳光
      addDirectionalLight: () => {
        data.renderer.shadowMap.enabled = true; // 将渲染器阴影渲染的属性打开
        var directionalLight = new THREE.DirectionalLight(0x0c0c0c); // 创建方向光
        directionalLight.castShadow = true; // 将平行光产生阴影的属性打开
        data.scene.add(directionalLight); // 将方向光添加到场景
      }
    };
  }
};
</script>

<style lang="scss" scoped>
.container {
  display: flex;
  align-items: center;
  justify-content: center;
}

#module {
}
</style>
